namespace Yaaf.WP7.NativeAccess.ComWrapper.AllDevices.COM_Native
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;

    using Yaaf.WP7.NativeAccess.Helper;
    using Yaaf.WP7.NativeAccess.Registry;

    internal class NativeRegistry
    {
        // Fields
        internal const int ERROR_SUCCESS = 0;
        private static bool initialized = false;
        private NativeDllInterop.INativeRegistry native;
        internal const int REG_DWORD = 4;
        internal const int REG_MULTI_SZ = 7;
        internal const int REG_SZ = 1;

        // Methods
        public NativeRegistry()
        {
            native = NativeDllInterop.GetRegistryInterface();
        }

        public int GetIntValue(string root, string path, string name)
        {
            uint result = 0;
            uint hr = native.GetDwordValue(root, path, name, out result);
            ThrowExceptionIfError(hr);
            return (int)result;
        }

        private static void ThrowExceptionIfError(uint hr)
        {
            if (hr != ERROR_SUCCESS)
            {
                switch (hr)
                {
                    case 2: throw new KeyNotFoundException();
                    case 13: throw new ArgumentException("Invalid format.");
                    case 5:
                    case 1260: throw new UnauthorizedAccessException();
                    default: throw new ArgumentException("Error getting value type: " + hr);
                }
            }

        }

        public string GetStringValue(string root, string path, string name)
        {
            string result = null;
            ThrowExceptionIfError(native.GetStringValue(root, path, name, out result));
            return result;
        }

        public IEnumerable<string> GetSubKeys(string root, string path)
        {
            string result = null;
            ThrowExceptionIfError(native.GetSubKeys(root, path, out result));
            
            if (result.Length <= 0)
            {
                return new List<string>();
            }
            return (from s in result.Split(new char[] { '|' })
                    where s.Length > 0
                    orderby s
                    select s);
        }

        public IEnumerable<string> GetSubValuesNames(string root, string path)
        {
            string result = null;
            ThrowExceptionIfError(native.GetValuesNames(root, path, out result));
            if (result.Length <= 0)
            {
                return new List<string>();
            }
            return (from s in result.Split(new char[] { '|' })
                    where s.Length > 0
                    select s).ToList<string>();
        }

        public RegistryValueKind GetValueType(string root, string path, string name)
        {
            uint result = 0;
            uint num2 = native.GetValueType(root, path, name, out result);
            ThrowExceptionIfError(num2);
            switch (result)
            {
                case 1:
                    return RegistryValueKind.String;
                case 2:
                    return RegistryValueKind.ExpandString;
                case 3:
                    return RegistryValueKind.Binary;
                case 4:
                    return RegistryValueKind.DWord;
                case 7:
                    return RegistryValueKind.MultiString;
                case 11:
                    return RegistryValueKind.Long;
            }
            return RegistryValueKind.Unknown;  // string.Format("Unknown ({0})", result);
        }


        public virtual void SetDwordValue(string root, string path, string name, uint value)
        {
            var hr = native.SetDwordValue(root, path, name, value);
            ThrowExceptionIfError(hr);
        }

        public virtual void SetStringValue(string root, string path, string name, string value)
        {
            var hr = native.SetStringValue(root, path, name, value);
            ThrowExceptionIfError(hr);
        }

        public string GetVersion()
        {
            string result = null;
            uint hr = native.GetVersion(out result);
            ThrowExceptionIfError(hr);
            return result;
        }
    }


}